package com.bluetooth;

import org.json.JSONArray;

import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.PluginResult;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;

import android.os.Environment;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.app.Activity;

public class BluetoothPlugin extends CordovaPlugin {
    private BluetoothAdapter _bluetooth = BluetoothAdapter.getDefaultAdapter();
    private List<String> _deviceArray = new ArrayList<>();
    private Activity _activity;
    private CallbackContext _sContext;
    private CallbackContext _dContext;
    private final static String _SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";   //蓝牙模块提供的新UUID号
    private final static String _EBS_UUID = "00001101-0000-1000-8000-00805F9B34FB"; // 依贝思印刷具的UUID号//0000ffe1-0000-1000-8000-00805f9b34fb
    BluetoothDevice _device = null;     //蓝牙设备
    BluetoothSocket _socket = null;      //蓝牙通信socket
    private InputStream _is;    //输入流，用来接收蓝牙数据
    private boolean _bRun = false;    //输入流，用来接收蓝牙数据
    private OutputStream _os; // 输出流，用来发送蓝牙数据
    private String lastWeight = ""; // 用于保存从蓝牙设备读取的原始报文
    
    @Override
    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
        super.initialize(cordova, webView);
        _activity = cordova.getActivity();
        _activity.registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
        _activity.registerReceiver(mReceiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED));
        _activity.registerReceiver(mReceiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED));
    }

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
        if ("checkBluetooth".equals(action)) {
            try {
                if (_bluetooth == null) {
                    callbackContext.error("失败，请确认手机是否有蓝牙功能");
                    return false;
                }
                callbackContext.success("成功，手机蓝牙功能正常");
                return true;
            } catch (Exception e) {
                callbackContext.error(e.getMessage());
                return false;
            }
        } else if ("openBluetooth".equals(action)) {
            try {
                if (_bluetooth.isEnabled() == false) {
                    _bluetooth.enable();
                } else {
                    callbackContext.success("成功，蓝牙功能已打开");
                }
                return true;
            } catch (Exception e) {
                callbackContext.error(e.getMessage());
                return false;
            }
        } else if ("searchDevices".equals(action)) {
            try {
                _deviceArray = new ArrayList<String>();
                if (_bluetooth.isDiscovering()) {
                    _bluetooth.cancelDiscovery();
                }
                _bluetooth.startDiscovery();
                PluginResult startResult = new PluginResult(PluginResult.Status.OK, "START");
                startResult.setKeepCallback(true);
                callbackContext.sendPluginResult(startResult);
                _sContext = callbackContext;
                return true;
            } catch (Exception e) {
                _bluetooth.cancelDiscovery();
                callbackContext.error(e.getMessage());
                return false;
            }
        } else if ("stopSearchDevices".equals(action)) {
            try {
                if (_bluetooth.isDiscovering()) {
                    _bluetooth.cancelDiscovery();
                }
                callbackContext.success("");
                return true;
            } catch (Exception e) {
                _bluetooth.cancelDiscovery();
                callbackContext.error(e.getMessage());
                return false;
            }
        } else if ("saveDevice".equals(action)) {
            try {
                File sdCardDir = Environment.getExternalStorageDirectory();
                File BuildDir = new File(sdCardDir, "/bluetooth");   //打开bluetooth目录，如不存在则生成
                if (BuildDir.exists() == false) BuildDir.mkdirs();
                File saveFile = new File(BuildDir, "bluetooth.txt");
                FileOutputStream stream = new FileOutputStream(saveFile);  //打开文件输入流
                stream.write(args.get(0).toString().getBytes());
                stream.close();
                callbackContext.success("保存成功");
                return true;
            } catch (Exception e) {
                callbackContext.error(e.getMessage());
                return false;
            }
        } else if ("saveDevices".equals(action)) {
            try {
                File sdCardDir = Environment.getExternalStorageDirectory();
                File BuildDir = new File(sdCardDir, "/bluetooth");   //打开bluetooth目录，如不存在则生成
                if (BuildDir.exists() == false) BuildDir.mkdirs();
                File saveFile = new File(BuildDir, "bluetooths.txt");
                FileOutputStream stream = new FileOutputStream(saveFile);  //打开文件输入流
                stream.write(args.get(0).toString().getBytes());
                stream.close();
                callbackContext.success("保存成功");
                return true;
            } catch (Exception e) {
                callbackContext.error(e.getMessage());
                return false;
            }
        } else if ("getSavedDevice".equals(action)) {
            try {
                File sdCardDir = Environment.getExternalStorageDirectory();
                File BuildDir = new File(sdCardDir, "/bluetooth");   //打开bluetooth目录，如不存在则生成
                if (BuildDir.exists() == false) BuildDir.mkdirs();
                File savedFile = new File(BuildDir, "bluetooth.txt");
                if (!savedFile.exists()) {
                    callbackContext.success("");
                } else {
                    InputStream stream = new FileInputStream(savedFile);
                    byte[] buffer = new byte[(int) savedFile.length()];
                    stream.read(buffer);
                    stream.close();
                    callbackContext.success(new String(buffer));
                }
                return true;
            } catch (Exception e) {
                callbackContext.error(e.getMessage());
                return false;
            }
        } else if ("getSavedDevices".equals(action)) {
            try {
                File sdCardDir = Environment.getExternalStorageDirectory();
                File BuildDir = new File(sdCardDir, "/bluetooth");   //打开bluetooth目录，如不存在则生成
                if (BuildDir.exists() == false) BuildDir.mkdirs();
                File savedFile = new File(BuildDir, "bluetooths.txt");
                if (!savedFile.exists()) {
                    callbackContext.success("");
                } else {
                    InputStream stream = new FileInputStream(savedFile);
                    byte[] buffer = new byte[(int) savedFile.length()];
                    stream.read(buffer);
                    stream.close();
                    callbackContext.success(new String(buffer));
                }
                return true;
            } catch (Exception e) {
                callbackContext.error(e.getMessage());
                return false;
            }
        } else if ("getData".equals(action)) {
            try {
                if (lastWeight.isEmpty()) {
                    callbackContext.error("getData未获取到蓝牙数据");
                } else {
                    callbackContext.success(lastWeight);
                }
                return true;
            } catch (Exception e) {
                callbackContext.error(e.getMessage());
                return false;
            }
        } else if("sendData".equals(action)) {
            try {
                if (_bRun) {
                    callbackContext.error("请稍等,发送数据中...");
                    return true;
                }
                _bRun = true;
                if (_bluetooth.isDiscovering()) {
                    _bluetooth.cancelDiscovery();
                }
                PluginResult startResult = new PluginResult(PluginResult.Status.OK, "START");
                startResult.setKeepCallback(true);
                callbackContext.sendPluginResult(startResult);
                _dContext = callbackContext;
                if(_os == null) {
                    _dContext.error("请先连接设备蓝牙");
                    return false;
                }
                new Thread() {
                    @Override
                    public void run() {
                        try {
                            if(args.get(0) == null || "".equals(args.get(0).toString())) {
                                _dContext.error("参数不能为空");
                            } else {
                                String orginStr = args.get(0).toString();
                                if(orginStr.lastIndexOf("\r") != orginStr.length() - 1) {
                                    orginStr = orginStr + "\r";
                                }
                                _os.write(orginStr.getBytes("UTF-8"));
                                _dContext.success(orginStr);
                            }
                        } catch (Exception e) {
                            _dContext.error(e.getMessage());
                        } finally {
                            _bRun = false;
                        }
                    }
                }.start();
                return true;
            } catch (Exception e) {
                _bRun = false;
                _dContext.error(e.getMessage());
                return false;
            }
        } else if("connectDevice".equals(action)) {
            try {
                PluginResult startResult = new PluginResult(PluginResult.Status.OK, "START");
                startResult.setKeepCallback(true);
                callbackContext.sendPluginResult(startResult);
                _dContext = callbackContext;
                if (_bluetooth.isDiscovering()) {
                    _bluetooth.cancelDiscovery();
                }
                if (args.get(0) == null || "".equals(args.get(0).toString())) {
                    _dContext.error("请先选择需要连接的设备");
                    return false;
                }
                new Thread() {
                    @Override
                    public void run() {
                        try {
                            _device = _bluetooth.getRemoteDevice(args.get(0).toString());
                            _socket = _device.createRfcommSocketToServiceRecord(UUID.fromString(_SPP_UUID));
                            if (_socket == null) {
                                _dContext.error("socket打开失败");
                                return;
                            }
                            _socket.connect();
                            _is = _socket.getInputStream();
                            _dContext.success("连接成功！");

                            // 创建线程持续读取蓝牙数据
                            new Thread(() -> {
                                try {
                                    byte[] buffer = new byte[64];
                                    int len;
                                    while (true) {
                                        if (_is != null && (len = _is.read(buffer)) > 0) {
                                            // 将读取到的原始报文存入 lastWeight
                                            lastWeight = new String(buffer, 0, len);
                                        }
                                    }
                                } catch (IOException e) {
                                    //lastWeight = ""; // 如果读取失败，暂时不要清空数据
                                }
                            }).start();

                        } catch (Exception e) {
                            _dContext.error(e.getMessage());
                        }
                    }
                }.start();
                return true;
            } catch (Exception e) {
                _dContext.error(e.getMessage());
                return false;
            }         
        } else {
            return false;
        }
    }

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            // 查找到设备action
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                // 得到蓝牙设备
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
                    // 未配对的，添加到设备列表
                    _deviceArray.add(device.getName() + "\n" + device.getAddress());
                } else {
                    // 已配对的，添加到设备列表
                    _deviceArray.add(device.getName() + "\n" + device.getAddress());
                }
                // 搜索完成action
            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                if (_bluetooth.isDiscovering()) {
                    _bluetooth.cancelDiscovery();
                }
                if (_sContext != null) {
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < _deviceArray.size(); i++) {
                        sb.append(_deviceArray.get(i));
                        if (i != _deviceArray.size() - 1) {
                            sb.append("\n\n");
                        }
                    }
                    PluginResult startResult = new PluginResult(PluginResult.Status.OK, sb.toString());
                    startResult.setKeepCallback(false);
                    _sContext.sendPluginResult(startResult);
                }
            }
        }
    };

    public static byte[] readStream(InputStream inStream) throws Exception {
//         ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
//         byte[] buffer = new byte[1024];
//         int len = -1;
//         while ((len = inStream.read(buffer)) != -1) {
//             boolean flag = false;
//             for (int i = 0; i < len; i++) {
//                 if ((buffer[i] == 0x0d) && (buffer[i + 1] == 0x0a)) {
//                     outSteam.write(buffer, 0, i + 1);
//                     flag = true;
//                     break;
//                 }
//             }
//             if (flag) break;
//         }
//         outSteam.close();
//         return outSteam.toByteArray();
        byte[] buffer = new byte[64];
        inStream.read(buffer);
        return buffer;
    }

}